﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Business;
using Business.Dicionary;
using Business.Entity.Estoque.Produto;
using Business.Entity.Vendas.Pedido.ClassesRelacionadas;
using Business.Entity.Vendas.Pedido.Restaurante;
using Business.Entity.Vendas.Pedido.Restaurante.ClassesRelacionadas;
using Business.Enum;
using FluentNHibernate.Conventions;
using Vendas.Controls;
using Vendas.Dialogs;


namespace Vendas.Forms
{
    public partial class PedidoControl : DevExpress.XtraEditors.XtraUserControl, IPedidoRestauranteItem
    {
        public ModoPesquisaProduto ModoPesquisa { get; set; }

        public PedidoControl()
        {
            InitializeComponent();
            TelaPedidoControl = this;
            localPedidoRestauranteDicionaryBindingSource.DataSource
                = new LocalPedidoRestauranteDicionary();

        }

        public PedidoControl(PedidoRestaurante pedido)
        {
            InitializeComponent();
            TelaPedidoControl = this;
            localPedidoRestauranteDicionaryBindingSource.DataSource
                = new LocalPedidoRestauranteDicionary();
            pedidoRestauranteBindingSource.Clear();
            pedidoRestauranteBindingSource.Add(pedido);
            Pedido = Pedido;
        }
        public void AbrirPedido(LocalPedidoRestaurante local)
        {
            Pedido = new PedidoRestaurante();
            var controle = new ControlePedido();
            controle.Controle = Properties.Settings.Default.NumeroControle;

            switch (local)
            {
                case LocalPedidoRestaurante.Mesa:
                    var numMesa = new FormNumeroMesa();
                    var mesa = numMesa.GetMesa("Informe o número da mesa");
                    if (mesa == 0)
                    {
                        RaisePedidoCancelado();
                        return;
                    }
                    Pedido.Mesa = mesa;
                    mesaTextEdit.Visible = true;
                    mesaLabel.Visible = true;
                    numMesa.Dispose();
                    controle.Chave = "Mesa" + Pedido.Mesa + "." + controle;
                    break;
                case LocalPedidoRestaurante.Balcao:
                    controle.Chave = "Balcao" + controle;
                    break;
                case LocalPedidoRestaurante.Entrega:
                    controle.Chave = "Entrega" + controle;
                    break;
            }
            if (Properties.Settings.Default.NumeroControle >= 99)
            {
                Properties.Settings.Default.NumeroControle = 1;
            }
            else
                Properties.Settings.Default.NumeroControle += 1;
            Properties.Settings.Default.Save();
            RepositoryBase<ControlePedido>.Save(controle);
            ModoPesquisa = ModoPesquisaProduto.Descricao;
            Pedido.Local = local; Pedido.Controle = controle; Pedido.DataPedido = Utils.Configuracao.DiaProcessamento;
            Pedido.Cliente = Utils.Configuracao.PessoaPadrao;
            produtosBindingSource.DataSource = new List<ComposicaoProduto>(); pedidoRestauranteBindingSource.DataSource = Pedido;
            Visible = false;
            RaisePedidoAberto();
            Visible = true;
        }

        public PedidoRestaurante GetPedidoRestaurante()
        {
            var pedido = (PedidoRestaurante)pedidoRestauranteBindingSource.DataSource;
            if (pedido.Produtos.IsEmpty() && produtosBindingSource.Count > 0)
            {
                foreach (ComposicaoProduto prod in produtosBindingSource)
                {
                    pedido.Produtos.Add(prod);
                }
            }
            return pedido;
        }

        private void txtFiltro_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {

                if (txtFiltro.Text.Equals(""))
                {
                    txtQuantidade.Focus();
                }
                else
                {
                    string param;
                    IList<Produto> list;
                    switch (ModoPesquisa)
                    {
                        case ModoPesquisaProduto.Descricao:
                            AddProduto(Bonesoft.WindowsControls.Utils.Functions.SelecionaProduto(ProdutoRepository.GetByDescricao("%" + txtFiltro.Text + "%")));
                            LimparCampo();
                            break;
                        case ModoPesquisaProduto.CodBarras:
                            AddProduto(Bonesoft.WindowsControls.Utils.Functions.SelecionaProduto(ProdutoRepository.GetByCodBarra(txtFiltro.Text)));
                            LimparCampo();
                            break;
                        case ModoPesquisaProduto.Referencia:
                            AddProduto(Bonesoft.WindowsControls.Utils.Functions.SelecionaProduto(ProdutoRepository.GetByCodBarra("%" + txtFiltro.Text + "%")));
                            LimparCampo();
                            break;
                    }
                }
            }
        }

        private void LimparCampo()
        {
            txtQuantidade.Text = "1";
            txtFiltro.Text = "";
        }

        public enum ModoPesquisaProduto
        {
            Descricao,
            Referencia,
            CodBarras
        }

        private void txtQuantidade_KeyDown(object sender, KeyEventArgs e)
        {

        }


        public void AddProduto(Produto produto)
        {
            if (produto == null)
            {
                return;
            }
            if (txtQuantidade.Text.Equals(""))
            {
                txtQuantidade.Focus();
                MessageBox.Show("Informe a quantidade antes de informar o produto", "Atenção");
                return;
            }
            var p = ComposicaoProdutoRepository.
                CreateComposicaoProduto(produto, Convert.ToDecimal(txtQuantidade.Text));
            p.Sequencia = GetLastSequencia();
            produtosBindingSource.Add(p);
            ((PedidoRestaurante) pedidoRestauranteBindingSource.Current).Produtos = (IList<ComposicaoProduto>) 
                produtosBindingSource.DataSource;
            OnOnProdutoAdicionado(new PedidoEventArgs()
            {
                Pedido = this
            });
            var ncm = p.Produto.NCM;
            LimparCampo();
            
        }

        private int GetLastSequencia()
        {
            int sq = 1;
            foreach (ComposicaoProduto prod in produtosBindingSource)
            {
                if (prod.Sequencia > sq)
                {
                    sq = prod.Sequencia + 1;
                }
            }
            return sq;
        }

        public void AddProduto(ComposicaoProduto produto)
        {
            produto.Sequencia = produtosBindingSource.Count + 1; produtosBindingSource.Add(produto);
        }

        public void ConfirmarPedido()
        {
            if (!Pedido.Confirmado)
            {
                RestauranteUtils.ImprimirPedido(GetPedidoRestaurante());
                RaisePedidoConfirmado();
            }


        }

        public void FinalizarEdicao()
        {
            composicaoBindingSource.EndEdit();
            produtosBindingSource.EndEdit();
            pedidoRestauranteBindingSource.EndEdit();
        }

        public void CancelarPedido()
        {
            RaisePedidoCancelado();
        }

        public void FecharPedido()
        {
            produtosBindingSource.EndEdit();
            composicaoBindingSource.EndEdit();
            pedidoRestauranteBindingSource.EndEdit();

            Pedido = GetPedidoRestaurante();
            if (!Pedido.Confirmado)
            {
                ConfirmarPedido();
            }

            if (VendaUtils.FecharPedidoRestaurante(Pedido)) RaisePedidoFechado();
        }

        public void ParcialMesa()
        {
            if (Pedido.Local == LocalPedidoRestaurante.Mesa)
            {
                RestauranteUtils.ParcialMesa(GetPedidoRestaurante());
            }
        }

        public void AlterarCliente()
        {
            throw new NotImplementedException();
        }

        public event PedidoConfirmadoEventHandler OnPedidoConfirmado = FormPedidoConfirmado;

        private static void FormPedidoConfirmado(object sender, PedidoEventArgs pedidoEventArgs)
        {

        }

        public event PedidoCanceladoEventHandler OnPedidoCancelado = FormPedidoCancelado;

        private static void FormPedidoCancelado(object sender, PedidoEventArgs pedidoEventArgs)
        {

        }

        public event PedidoFechadoEventHandler OnPedidoFechado = FormPedidoFechado;

        private static void FormPedidoFechado(object sender, PedidoEventArgs pedidoEventArgs)
        {

        }

        public event PedidoAbertoEventHandler OnPedidoAberto = FormPedidoAberto;



        private static void FormPedidoAberto(object sender, PedidoEventArgs pedidoEventArgs)
        {

        }

        public event LocalPedidoAlterado OnLocalPedidoAlterado = FormLocalPedidoAlterado;
        public event ProdutoAdicionadoEventHandler OnProdutoAdicionado;
        public event ProdutoExcluidoEventHandler OnProdutoExcluido;

        protected virtual void OnOnProdutoExcluido(PedidoEventArgs e)
        {
            ProdutoExcluidoEventHandler handler = OnProdutoExcluido;
            if (handler != null) handler(this, e);
        }

        protected virtual void OnOnProdutoAdicionado(PedidoEventArgs e)
        {
            ProdutoAdicionadoEventHandler handler = OnProdutoAdicionado;
            if (handler != null) handler(this, e);
        }


        private static void FormLocalPedidoAlterado(object sender, LocalPedidoAlteradoEventArgs localPedidoAlteradoEventArgs)
        {

        }

        public MesaTileControl TileControl { get; set; }

        public PedidoRestaurante Pedido
        {
            get
            {
                return (PedidoRestaurante)pedidoRestauranteBindingSource.Current;
            }
            set
            {
                pedidoRestauranteBindingSource.DataSource = value;
            }
        }

        public PedidoControl TelaPedidoControl { get; set; }
        private bool _confirmado;
        public bool Confirmado
        {
            get { return _confirmado; }
        }

        public void RaisePedidoConfirmado()
        {
            var e = new PedidoEventArgs();
            e.Pedido = this;
            OnPedidoConfirmado(this, e);
            _confirmado = true;

        }
        public void RaisePedidoCancelado()
        {
            var e = new PedidoEventArgs();
            e.Pedido = this;
            OnPedidoCancelado(this, e);
        }
        public void RaisePedidoAberto()
        {
            var e = new PedidoEventArgs();
            e.Pedido = this;
            OnPedidoAberto(this, e);
        }
        public void RaisePedidoFechado()
        {
            var e = new PedidoEventArgs();
            e.Pedido = this;
            OnPedidoFechado(this, e);
        }

        private void RaiseLocalPedidoAlterado(LocalPedidoRestaurante oldValue, LocalPedidoRestaurante newValue)
        {
            var e = new LocalPedidoAlteradoEventArgs();
            e.New = newValue;
            e.Old = oldValue;
            OnLocalPedidoAlterado(this, e);
        }

        private void cmdFecharPedido_Click(object sender, EventArgs e)
        {

        }

        private decimal CalcularValorPedido()
        {
            decimal total = 0;
            foreach (ComposicaoProduto prod in produtosBindingSource)
            {
                total += prod.Valor;
            }
            return total;
        }

        private void cmdCancelarPedido_Click(object sender, EventArgs e)
        {
            CancelarPedido();
        }

        private void cmdConfirmarPedido_Click(object sender, EventArgs e)
        {
            ConfirmarPedido();
        }

        private void PedidoControl_KeyDown(object sender, KeyEventArgs e)
        {
            textEdit1_KeyDown(sender, e);
        }

        public void ChangeModoPesquisa(ModoPesquisaProduto modoPesquisaProduto)
        {
            ModoPesquisa = modoPesquisaProduto;
            switch (modoPesquisaProduto)
            {
                case ModoPesquisaProduto.Descricao:
                    descricaoFiltroLabel.Text = "Descrição";
                    break;
                case ModoPesquisaProduto.CodBarras:
                    descricaoFiltroLabel.Text = "Código de barras";
                    break;
                case ModoPesquisaProduto.Referencia:
                    descricaoFiltroLabel.Text = "Referência";
                    break;
            }
        }


        public void EditarComposicao()
        {
            try
            {

                var c = (ComposicaoProduto)produtosBindingSource.Current;
                if (c != null)
                {
                    if (c.Produto.Ippt == Ippt.Propria || !Utils.Configuracao.LimitarComposicaoParaProprios)
                    {
                        var comp = new FormComposicao((ComposicaoProduto)produtosBindingSource.Current);
                        comp.ShowDialog();
                    }
                    else
                    {
                        MessageBox.Show("Não é possível compor mercadorias de terceiros.", "Alerta!");
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Erro ao carregar composição.\n" + ex.Message);
            }
        }

        public void PesquisarDescricao()
        {
            ChangeModoPesquisa(ModoPesquisaProduto.Descricao);
        }

        public void PesquisarReferencia()
        {
            ChangeModoPesquisa(ModoPesquisaProduto.Referencia);
        }

        public void PesquisarCodBarra()
        {
            ChangeModoPesquisa(ModoPesquisaProduto.CodBarras);
        }

        private void produtosBindingSource_CurrentItemChanged(object sender, EventArgs e)
        {

        }

        private void localComboBoxEdit_EditValueChanged(object sender, EventArgs e)
        {

        }

        private void localComboBoxEdit_EditValueChanging(object sender, DevExpress.XtraEditors.Controls.ChangingEventArgs e)
        {
            var newValue = (LocalPedidoRestaurante)e.NewValue;
            var oldValue = (LocalPedidoRestaurante)e.OldValue;
            if (newValue == LocalPedidoRestaurante.Mesa)
            {
                if (newValue == LocalPedidoRestaurante.Mesa && oldValue != LocalPedidoRestaurante.Mesa)
                {
                    var f = new FormNumeroMesa();
                    var n = f.GetMesa();
                    if (f.DialogResult == DialogResult.Cancel || n == 0)
                    {
                        localComboBoxEdit.EditValue = oldValue;
                        e.Cancel = true;
                        return;
                    }
                }
                mesaLabel.Visible = true;
                mesaTextEdit.Visible = true;
            }
            else
            {
                mesaLabel.Visible = false;
                mesaTextEdit.Visible = false;
            }

            RaiseLocalPedidoAlterado((LocalPedidoRestaurante)e.OldValue, (LocalPedidoRestaurante)e.NewValue);
        }

        public void PedidoConfirmado()
        {
            RaisePedidoConfirmado();
            RestauranteUtils.ImprimirPedido(Pedido);
        }

        public void PedidoFechado()
        {

            RaisePedidoFechado();
        }

        public void PedidoCancelado()
        {
            RaisePedidoCancelado();
        }

        private void textEdit1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {
                if (txtFiltro.Text.Equals(""))
                {
                    txtQuantidade.Focus();
                }
                else
                    switch (ModoPesquisa)
                    {
                        case ModoPesquisaProduto.Descricao:
                            AddProduto(Bonesoft.WindowsControls.Utils.Functions.SelecionaProduto(ProdutoRepository.GetByDescricao(txtFiltro.Text)));
                            break;
                        case ModoPesquisaProduto.Referencia:
                            AddProduto(Bonesoft.WindowsControls.Utils.Functions.SelecionaProduto(ProdutoRepository.GetByReferencia(txtFiltro.Text)));
                            break;
                        case ModoPesquisaProduto.CodBarras:
                            AddProduto(Bonesoft.WindowsControls.Utils.Functions.SelecionaProduto(ProdutoRepository.GetByCodBarra(txtFiltro.Text)));
                            break;
                    }
            }

            if (e.KeyData == Keys.Delete)
            {
                var result = MessageBox.Show("Deseja realmente excluir este item?",
                    "Atenção", MessageBoxButtons.YesNo);
                if (result == DialogResult.Yes)
                {
                    produtosBindingSource.Remove(produtosBindingSource.Current);
                    OnOnProdutoExcluido(new PedidoEventArgs()
                    {
                        Pedido = this
                    });
                }
            }
            if (e.KeyData == Keys.Up)
            {
                produtosBindingSource.MovePrevious();
            }
            if (e.KeyData == Keys.Down)
            {
                produtosBindingSource.MoveNext();
            }
            
        }

        private void PedidoControl_Load(object sender, EventArgs e)
        {
            txtFiltro.Focus();
        }

        private void PedidoControl_VisibleChanged(object sender, EventArgs e)
        {
            txtFiltro.Focus();
        }

        public void ConfigurarFoco()
        {
            txtFiltro.Focus();
        }


        public void MostrarObservacoes()
        {
            Pedido.Observacoes = FormObservacoes.GetObservacao(Pedido.Observacoes);
        }

        private void txtQuantidade_KeyDown_1(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Enter)
            {
                if (!txtQuantidade.Text.Equals(""))
                {
                    txtFiltro.Focus();
                }
                else
                {
                    MessageBox.Show("Informe uma quantidade");
                    txtQuantidade.Focus();
                }
            }
            
        }

        private void txtQuantidade_Leave(object sender, EventArgs e)
        {
            if (txtQuantidade.Text.Equals(""))
            {
                txtQuantidade.Text = "1";
            }
        }
    }

}